package shopping.demo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shopping.demo.cache.GoodsCache;
import shopping.demo.dao.GoodsDao;
import shopping.demo.entities.Goods;
import shopping.demo.exception.NotExistException;
import shopping.demo.exception.goods.GoodCountNotEnoughException;
import shopping.demo.exception.goods.GoodNotExistException;
import shopping.demo.exception.goods.GoodNotValidException;

import java.util.List;

@Service
@Slf4j
public class GoodsService {
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private GoodsCache goodsCache;
    private final Object lock = new Object();

//    @PostConstruct
//    public void init() {
//        for(Goods goods:goodsDao.findAll()) {
//            goodsCache.setGoodsCache(goods);
//        }
//        logger.info("Goods预热完毕");
//    }

    public List<Goods> FindAll() {
        List<Goods> goods = goodsCache.getGoods();
        return goods.size() == 0? goodsDao.findAll():goods;
    }

    public List<Goods> FindKilled() {
        List<Goods> kills = goodsCache.getKills();
        return kills.size() == 0?goodsDao.findKilled():kills;
    }

    public Goods FindById(Integer id) {
        Goods goods = goodsCache.getGoodsCache(id);
        //缓存未命中
        if(goods == null) {
            synchronized (this.lock) {
                //进行二次检测，上面操作为非原子，可能多个线程都进入分支
                goods = goodsCache.getGoodsCache(id);
                if(goods == null) {
                    Goods new_goods = goodsDao.findById(id);
                    if(new_goods == null) {
                        throw new GoodNotExistException();
                    }
                    //更新缓存
                    goodsCache.setGoodsCache(new_goods);
                    return new_goods;
                }else {
                    return goods;
                }
            }
        }
        return goods;
    }

    @Transactional
    public void DeleteById(Integer id) throws Exception{
        //对应删除缓存
        int count = goodsDao.deleteById(id);
        if(count == 0) {
            throw new GoodNotExistException();
        }
        goodsCache.deleteGoodsCache(id);
    }

    @Transactional
    public void changePrice(Integer id, Integer price) throws Exception {
        //先删除缓存
        goodsCache.deleteGoodsCache(id);
        //再更新数据库（等下一次访问该数据时候再更新缓存）
        int count = goodsDao.changePrice(id, price);
        if(count == 0) {
            throw new NotExistException("商品" + id);
        }
    }

    @Transactional
    public void countDown(Integer id,Integer count) throws Exception{
        Goods goods = goodsDao.findById(id);
        //不存在该商品
        if(goods == null) {
            throw new GoodNotExistException();
        }
        //库存不足
        if(goods.getCount() < count) {
            throw new GoodCountNotEnoughException();
        }
        //删除缓存
        goodsCache.deleteGoodsCache(id);

        goodsDao.countDown(id,count);
    }

    @Transactional
    public void setKilled(Integer id) {
        //数据库中将Kill字段变为1
        goodsDao.setKilled(id);
        //将缓存中的goods对象的kill属性也变为1
        Goods goods = goodsCache.getGoodsCache(id);
        goods.setKill(1);
        goodsCache.setGoodsCache(goods);
        //在缓存层中进行一个加载
        goodsCache.setKill(id);
    }

    @Transactional
    public void insertGoods(Goods goods) throws Exception{
        //说明该商品号已被使用
        if(goodsDao.findById(goods.getId()) != null) {
            throw new GoodNotValidException();
        }
        goodsDao.insertGoods(goods.getId(),goods.getName(), goods.getCount(), goods.getPrice());
    }
}
